package com.ft.oa.service.development.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ft.oa.domain.development.DevProduct;
import com.ft.oa.domain.development.ProductVersion;
import com.ft.oa.domain.dto.ApiResult;
import com.ft.oa.enums.ManagerEnum;
import com.ft.oa.mapper.development.DevProductMapper;
import com.ft.oa.mapper.development.ProductVersionMapper;
import com.ft.oa.service.development.DevProductService;
import com.ft.oa.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DevProductServiceImpl implements DevProductService {

    @Resource
    private DevProductMapper devProductMapper;
    @Resource
    private ProductVersionMapper productVersionMapper;

    @Override
    public List<DevProduct> list() {

        QueryWrapper<DevProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(DevProduct::getDel, false);
        List<DevProduct> list = devProductMapper.selectList(wrapper);

        return list;
    }

    @Override
    public ApiResult count() {

        QueryWrapper<ProductVersion> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(ProductVersion::getCategory, 1)
                .eq(ProductVersion::getState, 0);
        Integer productCount = productVersionMapper.selectCount(wrapper);

        QueryWrapper<ProductVersion> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda()
                .eq(ProductVersion::getCategory, 2)
                .eq(ProductVersion::getState, 0);
        Integer frameworkCount = productVersionMapper.selectCount(wrapper2);


        HashMap<String, Integer> result = new HashMap<>();
        result.put("productCount", productCount);
        result.put("frameworkCount", frameworkCount);


        return ApiResult.successWithData(result);
    }

    @Override
    @Transactional
    public ApiResult add(DevProduct product) {

        QueryWrapper<DevProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(DevProduct::getName, product.getName());
        Integer count = devProductMapper.selectCount(wrapper);
        if(count > 0){
            return ApiResult.builder().code(20004).msg("产品名重复").build();
        }
        product.setCreateTime(LocalDateTime.now());
        product.setUpdateTime(LocalDateTime.now());
        //创建产品
        int insert = devProductMapper.insert(product);
        //创建产品版本
        ProductVersion defaultProductVersion = getDefaultProductVersion(product);

        int insert1 = productVersionMapper.insert(defaultProductVersion);
        return ApiResult.simpleSuccess();
    }

    @Override
    @Transactional
    public ApiResult del(DevProduct product) {
        LambdaUpdateChainWrapper<DevProduct> wrapper = new LambdaUpdateChainWrapper<>(devProductMapper);

        boolean update = wrapper.eq(DevProduct::getId, product.getId())
                .set(DevProduct::getDel, true)
                .set(DevProduct::getDelTime, LocalDateTime.now())
                .update();

        return ApiResult.simpleSuccess();
    }

    @Override
    @Transactional
    public ApiResult update(DevProduct product) {

        LambdaUpdateChainWrapper<DevProduct> wrapper = new LambdaUpdateChainWrapper<>(devProductMapper);

        boolean update = wrapper.eq(DevProduct::getId, product.getId())
                .set(StringUtils.hasText(product.getInfo()), DevProduct::getInfo, product.getInfo())
                .set(DevProduct::getUpdateTime, LocalDateTime.now())
                .update();

        if(StringUtils.hasText(product.getVersions())){
            QueryWrapper<ProductVersion> pvWrapper = new QueryWrapper<>();
            pvWrapper.lambda()
                    .eq(ProductVersion::getProductId, product.getId())
                    .eq(ProductVersion::getCategory, 1)
                    .eq(ProductVersion::getProductVersions, product.getVersions());

            List<ProductVersion> productVersions = productVersionMapper.selectList(pvWrapper);
            if(productVersions != null && productVersions.size() > 0){

                return ApiResult.builder().code(20005).msg("版本号重复").build();
            }else {

                ProductVersion version = getDefaultProductVersion(product);
                int insert = productVersionMapper.insert(version);
            }
        }

        return ApiResult.simpleSuccess();
    }

    private ProductVersion getDefaultProductVersion(DevProduct product){
        ProductVersion productVersion = new ProductVersion();
        productVersion.setCategory(1);
        productVersion.setProductVersions(product.getVersions());
        productVersion.setProductId(product.getId());
        productVersion.setState(0);
        return productVersion;
    }

    @Override
    public Page<ArrayList<DevProduct>> page(DevProduct product) {

        QueryWrapper<DevProduct> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(ManagerEnum.GENERAL.toString().equals(SecurityUtils.getCurrentUser().getManager()), DevProduct::getCreator ,SecurityUtils.getCurrentUser().getId())
                .eq(DevProduct::getDel, false)
                .like(StringUtils.hasText(product.getName()), DevProduct::getName, product.getName());

        Page<DevProduct> pageCondition = new Page<>(product.getPage(), product.getSize());

        Page<DevProduct> productPage = devProductMapper.selectPage(pageCondition, wrapper);

        List<ArrayList<DevProduct>> records = productPage.getRecords().stream()
                .map(e -> {
                    ArrayList<DevProduct> devProducts = new ArrayList<>();

                    QueryWrapper<ProductVersion> pvWrapper = new QueryWrapper<>();
                    pvWrapper.lambda()
                            .eq(ProductVersion::getProductId, e.getId())
                            .eq(ProductVersion::getState, 0);

                    List<ProductVersion> productVersions = productVersionMapper.selectList(pvWrapper);

                    Map<Integer, List<ProductVersion>> collect = productVersions.stream()
                            .collect(Collectors.groupingBy(ProductVersion::getCategory));

                    List<ProductVersion> category1Sorted = collect.get(1).stream().sorted(Comparator.comparing(ProductVersion::getId).reversed()).limit(3).collect(Collectors.toList());

                    e.setVersions(category1Sorted.get(0).getProductVersions());
                    if(collect.containsKey(2)){
                        List<ProductVersion> category2Sorted = collect.get(2).stream().sorted(Comparator.comparing(ProductVersion::getId).reversed()).limit(1).collect(Collectors.toList());
                        e.setFramework(category2Sorted.get(0).getProductVersions());
                        e.setFrameworkCount(collect.get(2).size());
                    }else {
                        e.setFramework("");
                        e.setFrameworkCount(0);
                    }

                    if(collect.containsKey(3)){
                        List<ProductVersion> category3Sorted = collect.get(3).stream().sorted(Comparator.comparing(ProductVersion::getId).reversed()).limit(1).collect(Collectors.toList());
                        e.setIterationVersions(category3Sorted.get(0).getProductVersions());
                        e.setIterationVersionsCount(collect.get(3).size());
                    }else {
                        e.setIterationVersions("");
                        e.setIterationVersionsCount(0);
                    }

                    if(collect.containsKey(4)){
                        List<ProductVersion> category4Sorted = collect.get(4).stream().sorted(Comparator.comparing(ProductVersion::getId).reversed()).limit(1).collect(Collectors.toList());
                        e.setTaskVersions(category4Sorted.get(0).getProductVersions());
                        e.setTaskVersionsCount(collect.get(4).size());
                    }else {
                        e.setTaskVersions("");
                        e.setTaskVersionsCount(0);
                    }

                    category1Sorted.forEach(
                            ee->{
                                devProducts.add(new DevProduct(e, ee));
                            }
                    );

                    return devProducts;

                })
                .collect(Collectors.toList());

        Page<ArrayList<DevProduct>> arrayListPage = new Page<>(product.getPage(), product.getSize(), productPage.getTotal());

        arrayListPage.setRecords(records);

        return arrayListPage;

    }
}
